package com.uzai.console.aop.exception;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.common.exception.BusinessException;
import com.uzai.common.result.ResponseCode;
import com.uzai.console.aop.ResponseResultConsole;
import com.uzai.console.common.utils.Tools;
import com.uzai.console.common.web.interceptor.CustomHttpServletRequestWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author jianghan
 * @date 2017/1/10
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 非法参数验证异常
     * @param ex
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public ResponseResultConsole handleMethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        String errmsg = "参数错误";
        if (fieldErrors!=null && fieldErrors.size()>0){
            errmsg = fieldErrors.get(0).getDefaultMessage();
        }
        logger.error("handleMethodArgumentNotValidException:errmsg={}",errmsg);
        return new ResponseResultConsole(ResponseCode.PARAMETER_EXCEPTION,"参数异常",errmsg);
    }

    /**
     * 业务层异常处理
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = BusinessException.class)
    @ResponseStatus(HttpStatus.OK)
    public ResponseResultConsole businessExceptionHandler(HttpServletRequest request, BusinessException exception) {
        StackTraceElement[] stackTraceElements = exception.getStackTrace();
        //logger.error("businessException:{}",exception.getMessage()+"::"+stackTraceElements[0].toString());
        logger.error(exception.getMessage(), exception);
        Integer code = exception.getCode();
        code = (code==null? ResponseCode.BUSINESS_EXCEPTION:code);
        return new ResponseResultConsole(code,exception.getMessage());
    }

    /**
     * 默认的异常处理
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseStatus(HttpStatus.OK)
    public ResponseResultConsole exceptionHandler(HttpServletRequest request, Exception exception) {
        logger.error("exceptionHandler:",exception);
        return new ResponseResultConsole(ResponseCode.ERROR,"系统异常!");
    }

    /**
     * 查询列表参数类型错误验证异常
     * @param ex
     * @return
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(value = HttpStatus.OK)
    public ResponseResultConsole handleHttpMessageNotReadableExceptionHandler(HttpMessageNotReadableException ex) {
        logger.error("handleMethodArgumentNotValidException:",ex);

        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

        //将参数放入重写的方法中
        if(httpServletRequest instanceof CustomHttpServletRequestWrapper){
            CustomHttpServletRequestWrapper customHttpServletRequestWrappe = (CustomHttpServletRequestWrapper)httpServletRequest;
            logger.error("错误参数={}",customHttpServletRequestWrappe.getBody());
        }

        String servletPath = Tools.getStr(httpServletRequest.getServletPath());

        //查询列表的方法返回返回空页面
        if(servletPath.contains("find") && (servletPath.contains("List") || servletPath.contains("Page"))){
            return new ResponseResultConsole(ResponseCode.SUCCESS,null, new Page<>());
        }else{//否则返回参数异常
            return new ResponseResultConsole(ResponseCode.ERROR,"参数异常!");
        }



    }
}
